package me.zynaga.ragecraft;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.CreatureType;
import org.bukkit.entity.LivingEntity;
import org.bukkit.inventory.ItemStack;

public final class Commands {

	private Ragecraft plugin;
	private CommandSender playerSender = null;
	private Player playerTarget = null;
	private World worldTarget = null;
	private boolean commandUsage = false;

	public Commands(Ragecraft instance) {

		plugin = instance;

	}

	public World world(CommandSender sender) {

		return world(sender, "");

	}

	public World world(CommandSender sender, String target) {

		World findWorld = null;
		Player findPlayer = null;

		if (!(target.equals(""))) {

			findWorld = plugin.getServer().getWorld(target);

			if (!(findWorld instanceof World)) {

				findWorld = null;

				plugin.log("World '" + target + "' doest not exist.");

			}

		} else if (sender instanceof Player) {

			findPlayer = (Player) sender;

			findWorld = findPlayer.getWorld();

		} else {

			findWorld = plugin.getServer().getWorlds().get(0);

		}

		return findWorld;

	}

	public Player player(CommandSender sender) {

		return player(sender, "");

	}

	public Player player(CommandSender sender, String target) {

		Player findPlayer = null;
		commandUsage = true;

		if (!(target.equals(""))) {

			findPlayer = plugin.getServer().getPlayer(target);

			if (!(findPlayer instanceof Player)) {

				findPlayer = null;
				notify("Player '" + target + "' is not online.");

			}

		} else if (sender instanceof Player) {

			findPlayer = (Player) sender;

		}

		return findPlayer;

	}

	public void notify(String consoleMessage) {

		notify(consoleMessage, "");

	}

	public void notify(String consoleMessage, String playerMessage) {

		if (!(consoleMessage.equals(""))) {
			if (playerSender instanceof Player) {
				playerSender.sendMessage(consoleMessage);
			}
			plugin.log(consoleMessage);
		}

		if (!(playerMessage.equals("")) && playerTarget instanceof Player && !(playerTarget.equals(playerSender))) {
			playerTarget.sendMessage(playerMessage);
		}

		commandUsage = false;

	}

	public boolean hasPermission(String commandA, String commandB) {

		//COMMAND OR ALIAS EXIST
		if (commandA.equalsIgnoreCase(commandB) || plugin.getCommand(commandB).getAliases().contains(commandA)) {

			//PLAYER ISSUED
			if (playerSender instanceof Player) {

				if (playerSender.isOp()) {

					return true;

				}

				return playerSender.hasPermission("rc." + commandB);

			//CONSOLE ISSUED
			} else {

				return true;

			}

		}

		return false;

	}

	public boolean send(String command, String[] args, CommandSender sender) {

		playerSender = sender;
		playerTarget = player(sender);
		worldTarget = world(sender);

		try {

			// WORLD
			if (hasPermission(command, "time")) {

				List<World> worldTargets = plugin.getServer().getWorlds();

				if (args.length >= 2) {

					worldTarget = null;

					if (args[0].matches("(add|set)") == true) {

						if (args.length >= 3) {

							worldTargets.clear();

							worldTarget = world(sender, args[2]);

						}

					} else {

						worldTargets.clear();

						worldTarget = world(sender, args[1]);

					}

					if (worldTarget != null) {

						worldTargets.add(worldTarget);

					}

				}

				if (worldTargets.isEmpty() == false) {

					long time = 0;

					if (args.length >= 1) {

						for (int i = 0; i < worldTargets.size(); i++) {

							if (args[0].equals("day")) {

								time = 7;

							} else if (args[0].equals("night")) {

								time = 20;

							} else if (args[0].equals("add") && args.length >= 2) {

								time = parseInt(args[1]);

								time = (worldTargets.get(i).getTime()  / 1000) - 6 + time;

							} else if (args[0].equals("set") && args.length >= 2) {

								time = parseInt(args[1]);

							} else {

								time = parseInt(args[0]);

							}
							
							time = time - 6;
							
							if (time < -5 || time > 17) {
								time = 18;
							}
							
							time = time * 1000;
							
							worldTargets.get(i).setTime(time);

						}

					}
					
					time = (worldTargets.get(0).getTime() / 1000) + 6;
					
					if (time < 0 || time > 23) {
						time = Math.abs(time - 24);
					}

					notify("Time in " + worldTargets.get(0).getName() + " is now " + String.valueOf(time) + "h!");

				} else {

					return true;

				}

			} else if (hasPermission(command, "bolt")) {

				if (args.length >= 1) {
					playerTarget = player(sender, args[0]);
				}

				if (playerTarget != null) {

					playerTarget.getWorld().strikeLightning(playerTarget.getLocation());

					notify(playerTarget.getName() + " was Striked with a Lightning Bolt!", "You were Striked with a Lightning Bolt!");

				}

			} else if (hasPermission(command, "thunder")) {

				if (args.length >= 1) {
					worldTarget = world(sender, args[0]);
				}

				if (worldTarget != null) {


					if (worldTarget.isThundering() == false) {

						worldTarget.setThundering(true);

						notify("Thundering started!");

					} else {

						worldTarget.setThundering(false);
						notify("Thundering Stopped!");

					}

				}

			} else if (hasPermission(command, "weather")) {

				if (args.length >= 1) {
					worldTarget = world(sender, args[0]);
				}

				if (worldTarget != null) {

					if (worldTarget.hasStorm() == false) {

						worldTarget.setStorm(true);

						notify("Weather started!");

					} else {

						worldTarget.setStorm(false);
						notify("Weather Stopped!");

					}

				}

			} else if (hasPermission(command, "god")) {

				if (args.length >= 1) {
					playerTarget = player(sender, args[0]);
				}

				if (playerTarget != null) {

					if (plugin.gods.contains(playerTarget) == true) {

						plugin.gods.remove(playerTarget);

						notify(playerTarget.getName() + " is no longer in God Mode!", "You are no longer in God Mode!");

					} else {

						playerTarget.setHealth(20);
						playerTarget.setFoodLevel(20);
						playerTarget.setFireTicks(0);
						playerTarget.setRemainingAir(20);
						playerTarget.setExhaustion(0);
						
						plugin.gods.add(playerTarget);

						notify(playerTarget.getName() + " is now in God Mode!", "You are now in God Mode!");

					}

				}

			} else if (hasPermission(command, "feed")) {

				if (args.length >= 1) {
					playerTarget = player(sender, args[0]);
				}

				if (playerTarget != null) {

					int value = 20;

					if (args.length >= 2) {
						value = parseInt(args[1]);
					}

					if (value + playerTarget.getFoodLevel() > 20) {
						value = 20 - playerTarget.getFoodLevel();
					}

					playerTarget.setFoodLevel(playerTarget.getFoodLevel() + value);

					notify(playerTarget.getName() + " was fed!", "You were fed!");

				}

			} else if (hasPermission(command, "kill")) {

				if (args.length >= 1) {
					playerTarget = player(sender, args[0]);
				}

				if (playerTarget != null) {

					playerTarget.setHealth(0);

					notify(playerTarget.getName() + " was killed!", "You were killed!");

				}

			} else if (hasPermission(command, "hurt")) {

				if (args.length >= 1) {
					playerTarget = player(sender, args[0]);
				}

				if (playerTarget != null) {

					int value = 1;

					if (args.length >= 2) {
						value = parseInt(args[1]);
					}

					if (playerTarget.getHealth() - value < 0) {
						value = playerTarget.getHealth();
					}

					playerTarget.setHealth(playerTarget.getHealth() - value);


					if (playerTarget.getHealth() > 0) {
						notify(playerTarget.getName() + " was hurt!", "You were hurt!");
					} else {
						notify(playerTarget.getName() + " was killed!", "You were killed!");
					}

				}

			} else if (hasPermission(command, "heal")) {

				if (args.length >= 1) {
					playerTarget = player(sender, args[0]);
				}

				if (playerTarget != null) {

					int value = 20;

					if (args.length >= 2) {
						value = parseInt(args[1]);
					}

					if (value + playerTarget.getHealth() > 20) {
						value = 20 - playerTarget.getHealth();
					}

					playerTarget.setHealth(playerTarget.getHealth() + value);

					notify(playerTarget.getName() + " was healed!", "You were healed!");

				}

			} else if (hasPermission(command, "survival")) {

				if (args.length >= 1) {
					playerTarget = player(sender, args[0]);
				}

				if (playerTarget != null) {

					playerTarget.setGameMode(GameMode.SURVIVAL);

					notify(playerTarget.getName() + "'s now in survival mode!", "You're now in survival mode!");

				}

			} else if (hasPermission(command, "creative")) {

				if (args.length >= 1) {
					playerTarget = player(sender, args[0]);
				}

				if (playerTarget != null) {

					playerTarget.setGameMode(GameMode.CREATIVE);

					notify(playerTarget.getName() + "'s now in creative mode!", "You're now in creative mode!");

				}

			} else if (hasPermission(command, "experience")) {

				if (args.length >= 2) {

					playerTarget = player(sender, args[1]);

				}

				if (playerTarget != null) {

					int amount = 0;

					if (args[0].equalsIgnoreCase("add")) {

						amount = playerTarget.getExperience() + parseInt(args[1]);

					} else if (args[0].equalsIgnoreCase("set")) {

						amount = parseInt(args[1]);

					} else {

						amount = parseInt(args[0]);

					}

					if (amount >= 0) {

						playerTarget.setExperience(amount);

						if (playerTarget.getExperience() > 0) {
							amount = playerTarget.getTotalExperience() / playerTarget.getExperience() * 100;

							notify(playerTarget.getName() + "'s is now at " + amount + "% from level up!", "You're now at " + amount + "% from level up!");
						} else {
							amount = playerTarget.getLevel();

							notify(playerTarget.getName() + "'s is now Level " + amount + "!", "You're now Level " + amount + "!");
						}


					}

				}

			} else if (hasPermission(command, "level")) {

				if (args.length >= 2) {

					playerTarget = player(sender, args[args.length - 1]);

				}

				if (playerTarget != null) {

					int amount = 0;

					if (args[0].equalsIgnoreCase("add")) {

						amount = playerTarget.getLevel() + parseInt(args[1]);;

					} else if (args[0].equalsIgnoreCase("set")) {

						amount = parseInt(args[1]);

					} else {

						amount = parseInt(args[0]);

					}

					if (amount >= 0) {

						playerTarget.setLevel(amount);

						notify(playerTarget.getName() + "'s is now Level " + amount + "!", "You're now Level " + amount + "!");

					}

				}

			} else if (hasPermission(command, "take")) {

				int amount = 1;
				Material material = null;
				ArrayList<String> idata = new ArrayList<String>();
				
				if (args.length >= 1) {
					
					if (args.length >= 2) {
						
						if (args.length >= 4) {
							playerTarget = player(sender, args[3]);
						}
						
						amount = parseInt(args[1]);

						if (amount <= 0) {

							amount = 1;

						}
						
					}
					
					idata.addAll(Arrays.asList(args[0].split(":")));
					
					if (idata.size() == 1) {
						idata.add("0");
					}
				
					if (parseInt(args[0]) > 0) {
						material = Material.getMaterial(parseInt(idata.get(0)));
					} else {
						material = Material.matchMaterial(idata.get(0).toUpperCase());
					}
					
					if (material.getId() == 0) {
						material = Material.STONE;
					}
					
				}

				if (playerTarget != null && material != null) {
					
					ItemStack iss = new ItemStack(material, amount, Short.MIN_VALUE, Byte.parseByte(idata.get(1)));

					playerTarget.getInventory().removeItem(iss);

					notify(amount + " of " + material.name() + " was taken from " + playerTarget.getName() + "!", amount + " of " + material.name() + " was taken from you!");

				}

			} else if (hasPermission(command, "give")) {

				int amount = 1;
				Material material = null;
				ArrayList<String> idata = new ArrayList<String>();
				
				if (args.length >= 1) {
					
					if (args.length >= 2) {
						
						if (args.length >= 4) {
							playerTarget = player(sender, args[3]);
						}
						
						amount = parseInt(args[1]);

						if (amount <= 0) {

							amount = 1;

						}
						
					}
					
					idata.addAll(Arrays.asList(args[0].split(":")));
					
					if (idata.size() == 1) {
						idata.add("0");
					}
					
					if (parseInt(args[0]) > 0) {
						material = Material.getMaterial(parseInt(idata.get(0)));
					} else {
						material = Material.matchMaterial(idata.get(0).toUpperCase());
					}
					
					if (material.getId() == 0) {
						material = Material.STONE;
					}
					
				}

				if (playerTarget != null && material != null) {
					
					ItemStack iss = new ItemStack(material, amount, Short.MIN_VALUE, Byte.parseByte(idata.get(1)));
					
					playerTarget.getInventory().addItem(iss);

					notify(amount + " of " + material.name() + " was given to " + playerTarget.getName() + "!", amount + " of " + material.name() + " was given to you!");
					
				}
				
			} else if (hasPermission(command, "inventory")) {
				
				if (args.length >= 2) {
					playerTarget = player(sender, args[1]);
				}
				
				if (playerTarget != null && args.length >= 1) {
					
					if (args[0].equalsIgnoreCase("clear")) {
						
						playerTarget.getInventory().clear();
						
						notify(playerTarget.getName() + "'s inventory is now empty!", "Your inventory is now empty!");
						
					} else if (args[0].equalsIgnoreCase("clear")) {
						
						
						
					}
					
				}
				
			} else if (hasPermission(command, "mob")) {

				CreatureType creature = null;
				Location location = null;
				int amount = 1;
				
				if (playerTarget != null) {
					
					location = playerTarget.getTargetBlock(null, 0).getLocation();
					
				}
				
				if (args.length >= 1) {
					
					if (args.length >= 2) {
						
						if (args.length >= 3) {
					
							if (args[2].contains(",")) {
								
								if (args.length >= 4) {
									worldTarget = world(sender, args[3]);
								}
								
								location = parseLocation(args[2], worldTarget);
								
							} else {
							
								playerTarget = player(sender, args[2]);

								if (playerTarget != null) {

									location = playerTarget.getLocation();

								}
							}
								
						}
					
						amount = parseInt(args[1]);

						if (amount >= 20) {

							amount = 20;

						} else if (amount <= 0) {

							amount = 1;

						}

					}

					creature = CreatureType.valueOf(args[0].toUpperCase());
				
				}
				
				if (location != null && creature != null) {
					
					for(int i = 0; i < amount; i++) {
						worldTarget.spawnCreature(location, creature);
					}
					
					notify("Spawned " + amount + " " + creature.getName() + "'s!", "Spawned " + amount + " " + creature.getName() + "'s!");
					
				}

			} else if (hasPermission(command, "wipe")) {
				
				Location location = null;
				int amount = 1;
				
				if (args.length >= 1) {
					
					if (args.length >= 2) {
						
						if (args[1].contains(",")) {
							
							if (args.length >= 3) {
								worldTarget = world(sender, args[2]);
							}
							
							location = parseLocation(args[1], worldTarget);
							plugin.log(location.toString());
						} else {

							playerTarget = player(sender, args[1]);

							if (playerTarget != null) {

								location = playerTarget.getLocation();

							}
						}
						
					} else if (playerTarget != null) {

						location = playerTarget.getLocation();

					}
					
					amount = parseInt(args[0]);

					if (amount >= 300) {

						amount = 300;

					} else if (amount <= 0) {

						amount = 1;

					}
				}

				if (location != null) {
					
					List<LivingEntity> creatures = worldTarget.getLivingEntities();
					
					for(int i = 0; i < creatures.size(); i++) {
						if (!(creatures.get(i) instanceof Player)){
							if (creatures.get(i).getLocation().distance(location) <= amount) {
								creatures.get(i).damage(1000);
							}
						}
					}
					
					notify("Killed all the creatures within " + amount + " block radius of location!", "Killed all the creatures within " + amount + " block radius of location!");
					
				}
					
			} else {

				notify("Command '" + command + "' under development.");

			}

		} catch (Exception e) {

			notify(e.getMessage());

		}


		return !(commandUsage);

	}
	
	public Location parseLocation(String value) {
		
		return parseLocation(value, null, ",");
		
	}

	public Location parseLocation(String value, String split) {
		
		return parseLocation(value, null, split);
		
	}

	public Location parseLocation(String value, World world) {
		
		return parseLocation(value, world, ",");
		
	}
	
	public Location parseLocation(String value, World world, String split) {
		
		Location location = null;
	
		String[] coords = value.split(split);
		
		if (coords.length == 3) {
			
			location = new Location(world, parseDouble(coords[0]), parseDouble(coords[1]), parseDouble(coords[2]));
			
		}
		
		return location;
		
	}

	public double parseDouble(String value) {

		double parse = 0.0;

		try {

			parse = Double.parseDouble(value);

		} catch (Exception e) {

		}

		return parse;

	}
	
	public int parseInt(String value) {

		int parse = 0;

		try {

			parse = Integer.parseInt(value);

		} catch (Exception e) {

		}

		return parse;

	}
}
